use {
    futures::{
        future::{BoxFuture, FutureExt},
        task::{ArcWake, waker_ref},
    },
    pr02_timer_future::TimerFuture,
    std::{
        future::Future,
        sync::{
            Arc, Mutex,
            mpsc::{Receiver, SyncSender, sync_channel},
        },
        task::Context,
        time::Duration,
    },
};

fn main() {
    let (executor, spawner) = new_executor_and_spawner();

    spawner.spawn(async {
        println!("howdy");
        TimerFuture::new(Duration::new(2, 0)).await;
        println!("done");
    });

    drop(spawner);

    executor.run()
}

struct Executor {
    ready_queue: Receiver<Arc<Task>>,
}

#[derive(Clone)]
struct Spawner {
    task_sender: SyncSender<Arc<Task>>,
}

struct Task {
    future: Mutex<Option<BoxFuture<'static, ()>>>,
    task_sender: SyncSender<Arc<Task>>,
}

impl Executor {
    fn run(&self) {
        // 细节：1.这里的while不是空转，当ready_queue没有任务时候，将线程主阻塞住，等待waker唤醒，重新将任务加入队列
        while let Ok(task) = self.ready_queue.recv() {
            let mut future_slot = task.future.lock().unwrap();
            // 细节：2.这里take方法，将future_slot变量的值Some<T>拿走，换成None给原来变量，这样确保了数据完整性和避免了借用冲突
            if let Some(mut future) = future_slot.take() {
                // 细节：4.这里waker_ref会对task实现ArcWake特质的waker_by_ref进行引用
                let waker = waker_ref(&task);
                let context = &mut Context::from_waker(&*waker);
                // 细节：3.这里的future是async{}（async 代码块）返回匿名Future，这个Future在编译时会生成一个状态机，来调度代码块中的代码，
                // 这里是在调用匿名Future的poll，并将封装Waker的Context传递给匿名Future的内部进行传递（唤醒链），无论匿名Future内部有多少
                // 层Future嵌套，最外层的Waker将传递至最后一层的每一个Future上（逐级传递复用，不同时持有，前一个完成，后一个开始），Future
                // 逐级获取逐级消费Waker（Waker接力），每消费一次都将task往任务队列中推一次，executor执行一次最外层Future的poll执行
                if future.as_mut().poll(context).is_pending() {
                    *future_slot = Some(future)
                }
            }
        }
    }
}

impl Spawner {
    fn spawn(&self, future: impl Future<Output = ()> + Send + 'static) {
        // 细节：5.boxed方法，是在FutureExt特质上实现的，专门为Future实现的方法，所有
        // 这里引入FutureExt特质才可以调用boxed方法
        let future = future.boxed();
        let task = Arc::new(Task {
            future: Mutex::new(Some(future)),
            task_sender: self.task_sender.clone(),
        });

        self.task_sender.send(task).expect("任务列队已满")
    }
}

impl ArcWake for Task {
    fn wake_by_ref(arc_self: &Arc<Self>) {
        let cloned = arc_self.clone();
        arc_self.task_sender.send(cloned).expect("任务队列已满")
    }
}

fn new_executor_and_spawner() -> (Executor, Spawner) {
    const MAX_QUEUE_TASKS: usize = 10_000;
    let (task_sender, ready_queue) = sync_channel(MAX_QUEUE_TASKS);
    (Executor { ready_queue }, Spawner { task_sender })
}
